home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / mgraph / mgraph.c < prev    next >
C/C++ Source or Header  |  1994-03-22  |  13KB  |  449 lines

  1. /* Copyright 1994 Ralph Gonzalez */
  2.  
  3. /*
  4. *    FILE:        mgraph.c
  5. *    AUTHOR:        R. Gonzalez
  6. *    CREATED:    March 19, 1990
  7. *    MODIFIED:    March 15, 1994
  8. *                Adapted macgraph.c to agree with xgraph version
  9. *
  10. *   PROJECT CONTENTS:
  11. *   yourfiles.c, mgraph.c, ANSI, MacTraps libraries, MacHeaders option.
  12. *    
  13. *    mgraph.c contains several Macintosh routines to supplement
  14. *    a typical stdio-type application with a graphics window, so that
  15. *    you don't have to deal directly with the Macintosh Toolbox (see
  16. *    below.) Your program must #include "mgraph.h" and must call
  17. *    init_graphics() first.
  18. *    
  19. *    The device coordinate system (usually given in pixels) is norm-
  20. *    alized to -1 to 1 horizontally by default. The vertical limits
  21. *    depend on the screen's aspect ratio. This is used for placing and
  22. *    sizing the graphics window.
  23. *
  24. *    The window's own view coordinate system (which is used for
  25. *    drawing) is also normalized, by default to -1 to 1 horizontally
  26. *    and vertically. 
  27. *
  28. *    (The Macintosh Toolbox is a set of routines in ROM to produce the
  29. *    graphical user interface.  These Toolbox functions are declared in
  30. *    MacHeaders.  They are distinguished from my own functions by
  31. *    beginning with a capital letter.)
  32. */
  33.  
  34. # include    "mgraph.h"
  35. # include    <stdio.h>
  36.  
  37. /*---------------------------------------------------------------------*/
  38. /*    The following #define's may be adjusted to your taste: */
  39. /*---------------------------------------------------------------------*/
  40. # define    TITLE                "\pGraphics"
  41. /* # define    MOVABLE */                    /* use this if your program handles window moves */
  42. # define    BACKGROUND            BLACK    /* this is unused, see background_color(), below */
  43. # define    GRAPH_WIDTH            1.    /* Window sizing & placement in      */
  44. # define    GRAPH_HEIGHT        1.    /* normalized screen coords (below). */
  45. # define    GRAPH_CENTER_X        0.    
  46. # define    GRAPH_CENTER_Y        0.
  47.  
  48. /*---------------------------------------------------------------------*/
  49. /*    You can change these too if you want: */
  50. /*---------------------------------------------------------------------*/
  51. # define    NORM_WIDTH            2.    /* define normalized screen coords */
  52.                                     /* height depends on aspect ratio */
  53. # define    NORM_CENTER_X        0.
  54. # define    NORM_CENTER_Y        0.
  55. # define    VIEW_WIDTH            2.    /* define normalized window coords for drawing */
  56. # define    VIEW_HEIGHT            2.
  57. # define    VIEW_CENTER_X        0.
  58. # define    VIEW_CENTER_Y        0.
  59. /*---------------------------------------------------------------------*/
  60.  
  61. /*    These represent the dimensions of the graphics window given in
  62. *    actual window coordinates. Also the window coords of its center:
  63. */
  64. static double        gGraphWidth,    
  65.                     gGraphHeight,
  66.                     gGraphX,
  67.                     gGraphY;
  68.                     
  69. /*    These represent the dimensions of normalized window coordinate
  70. *    system used for drawing, and coords of its center:
  71. */
  72. static double        gViewWidth,        
  73.                     gViewHeight,
  74.                     gViewX,
  75.                     gViewY;
  76.  
  77. static int            transform_x(double),
  78.                     transform_y(double);
  79.  
  80. /* globals for Macintosh implementation */
  81. static WindowPtr    gGraphWindow,
  82.                     gConsoleWindow;
  83. static CursHandle    gCursor;
  84. static color        gPresentcolor;
  85. # define            NIL_POINTER            0L
  86. # define            MOVE_TO_FRONT        -1L
  87. # define            REMOVE_ALL_EVENTS    0
  88. # define            VISIBLE                1
  89. # define            NO_GO_AWAY            0
  90. # define            NIL_REF_CON            NIL_POINTER
  91.  
  92. /*    These represent the dimensions of the physical display device in
  93. *    device coords, and the device coords of its center:
  94. */
  95. static double        gDeviceWidth,    
  96.                     gDeviceHeight,
  97.                     gDeviceCenterX,
  98.                     gDeviceCenterY;
  99.                     
  100. /*    These represent the dimensions of the normalized device coordinate
  101. *    system, used for window sizing. The desired coords for the center
  102. *    of the device are also given:
  103. */
  104. static double        gNormalDeviceWidth,    
  105.                     gNormalDeviceHeight,
  106.                     gNormalDeviceCenterX,
  107.                     gNormalDeviceCenterY;
  108.  
  109. /************************************************************************
  110. *    You must call init_graphics() at the beginning of main().
  111. *    Likely don't need all these initializations; they are taken from Mark
  112. *    & Reed's "Macintosh Programming Primer", Addison-Wesley, 1989
  113. ************************************************************************/
  114. void    init_graphics(void)
  115. {
  116.     Rect        rectangle;
  117.     double        ratio,
  118.                 temp;
  119.     int            left,
  120.                 top,
  121.                 width,
  122.                 height;
  123.     
  124. /*    Need a stdio function call to produce the generic console environment
  125. *    BEFORE the remaining inits:
  126. */
  127.     printf("\n");
  128.     gConsoleWindow = FrontWindow();
  129.     
  130.     InitGraf(&thePort);
  131.     InitFonts();
  132.     FlushEvents(everyEvent,REMOVE_ALL_EVENTS);
  133.     InitWindows();
  134.     InitMenus();
  135.     TEInit();
  136.     InitDialogs(NIL_POINTER);
  137.     InitCursor();
  138.     
  139.     /* calculate device and normalized screen coord systems */
  140.     /* Note Macs use inverted y axis. This makes gDeviceHeight negative, */
  141.     /* which compensates the remaining equations automatically. */
  142.  
  143.     gDeviceWidth = screenBits.bounds.right - screenBits.bounds.left;
  144.     gDeviceHeight = screenBits.bounds.top - screenBits.bounds.bottom;    
  145.     gDeviceCenterX = gDeviceWidth/2;
  146.     gDeviceCenterY = -gDeviceHeight/2;
  147.     
  148.     ratio = get_screen_aspect_ratio();
  149.     
  150.     gNormalDeviceWidth = NORM_WIDTH;
  151.     gNormalDeviceHeight = gNormalDeviceWidth/ratio;
  152.     gNormalDeviceCenterX = NORM_CENTER_X;
  153.     gNormalDeviceCenterY = NORM_CENTER_Y;
  154.  
  155.     /* convert window location from normalized to device coords */
  156.     
  157.     temp = GRAPH_CENTER_X-GRAPH_WIDTH/2.;
  158.     ratio = gDeviceWidth/gNormalDeviceWidth;
  159.     left = gDeviceCenterX + (temp-gNormalDeviceCenterX) * ratio;
  160.     width = (ratio*GRAPH_WIDTH);
  161.     
  162.     temp = GRAPH_CENTER_Y+GRAPH_HEIGHT/2.;
  163.     ratio = gDeviceHeight/gNormalDeviceHeight;
  164.     top = (int) (gDeviceCenterY + (temp-gNormalDeviceCenterY) * ratio);
  165.     height = (int) (-ratio*GRAPH_HEIGHT);
  166.  
  167.     SetRect(&rectangle,left,top,left+width,top+height);
  168.     
  169.     /* create graphics window */
  170.  
  171. # ifdef MOVABLE
  172.         gGraphWindow = NewWindow(NIL_POINTER,&rectangle,TITLE,
  173.             VISIBLE,noGrowDocProc,(WindowPtr) MOVE_TO_FRONT,NO_GO_AWAY,NIL_REF_CON);
  174. # else
  175.         gGraphWindow = NewWindow(NIL_POINTER,&rectangle,TITLE,
  176.             VISIBLE,plainDBox,(WindowPtr) MOVE_TO_FRONT,NO_GO_AWAY,NIL_REF_CON);
  177. # endif
  178.     SetPort(gGraphWindow);
  179.  
  180.     gGraphX = width/2;
  181.     gGraphY = height/2;
  182.     gGraphWidth = width;
  183.     gGraphHeight = -height;
  184.     
  185.     set_graphics_coords(VIEW_WIDTH,VIEW_HEIGHT,VIEW_CENTER_X,VIEW_CENTER_Y);
  186.     pen_color(WHITE);
  187.     background_color(BLACK);
  188.     erase_graphics();
  189. }
  190.  
  191. /************************************************************************
  192. *    Return device aspect ratio: width/height
  193. ************************************************************************/
  194. double    get_screen_aspect_ratio(void)
  195. {
  196.     double    ratio;
  197.     
  198.     ratio = gDeviceWidth/gDeviceHeight;
  199.     if (ratio < 0.)
  200.         ratio = -ratio;
  201.         
  202.     return ratio;
  203. }
  204.  
  205. /************************************************************************
  206. *    Define view coordinate system for draw_line(), draw_circle(), etc.
  207. ************************************************************************/
  208. void    set_graphics_coords(double width,double height,double x,double y)
  209. {
  210.     gViewWidth = width;
  211.     gViewHeight = height;
  212.     gViewX = x;
  213.     gViewY = y;
  214. }
  215.  
  216. /************************************************************************
  217. *    Transform view coordinate x to window coordinates
  218. ************************************************************************/
  219. static int    transform_x(double x)
  220. {
  221.     return (int) (gGraphX+(x-gViewX)*gGraphWidth/gViewWidth);
  222. }
  223.  
  224. /************************************************************************
  225. *    Transform view coordinate y to window coordinates
  226. ************************************************************************/
  227. static int    transform_y(double y)
  228. {
  229.     return (int) (gGraphY+(y-gViewY)*gGraphHeight/gViewHeight);
  230. }
  231.  
  232. /************************************************************************
  233. *    pen_color() sets the current drawing color. 
  234. ************************************************************************/
  235. void    pen_color(color x)
  236. {    
  237.     gPresentcolor = x;
  238.     
  239.     switch (x)
  240.     {
  241.         case 0:    ForeColor(blackColor);
  242.                 break;
  243.         case 1:    ForeColor(whiteColor);
  244.                 break;
  245.         case 2:    ForeColor(redColor);
  246.                 break;
  247.         case 3:    ForeColor(yellowColor);
  248.                 break;
  249.         case 4:    ForeColor(greenColor);
  250.                 break;
  251.         case 5:    ForeColor(blueColor);
  252.                 break;
  253.         case 6:    ForeColor(cyanColor);
  254.                 break;
  255.         case 7:    ForeColor(magentaColor);
  256.                 break;
  257.         default:    break;
  258.     }
  259.     return;
  260. }
  261.  
  262. /************************************************************************
  263. *    background_color() sets the background drawing color.
  264. ************************************************************************/
  265. void    background_color(color x)
  266. {
  267.     switch (x)
  268.     {
  269.         case 0:    BackColor(blackColor);
  270.                 break;
  271.         case 1:    BackColor(whiteColor);
  272.                 break;
  273.         case 2:    BackColor(redColor);
  274.                 break;
  275.         case 3:    BackColor(yellowColor);
  276.                 break;
  277.         case 4:    BackColor(greenColor);
  278.                 break;
  279.         case 5:    BackColor(blueColor);
  280.                 break;
  281.         case 6:    BackColor(cyanColor);
  282.                 break;
  283.         case 7:    BackColor(magentaColor);
  284.                 break;
  285.         default:    break;
  286.     }
  287.     return;
  288. }
  289.  
  290. /************************************************************************
  291. *    erase_graphics() makes the graphics window the background color. 
  292. ************************************************************************/
  293. void    erase_graphics(void)
  294. {
  295.     EraseRect(&(gGraphWindow->portRect));
  296.  
  297.     return;
  298. }
  299.  
  300. /************************************************************************
  301. *    bring graphics window to front. 
  302. ************************************************************************/
  303. void    graphics_to_front(void)
  304. {
  305.     SelectWindow(gGraphWindow);
  306. }
  307.  
  308. /************************************************************************
  309. *    draw_line() is used to draw lines using view coordinates.
  310. ************************************************************************/
  311. void        draw_line(double x1,double y1,double x2,double y2)
  312. {
  313.     int        window_x1,
  314.             window_y1,
  315.             window_x2,
  316.             window_y2;
  317.  
  318.     window_x1 = transform_x(x1);
  319.     window_y1 = transform_y(y1);
  320.     window_x2 = transform_x(x2);
  321.     window_y2 = transform_y(y2);
  322.     
  323.     MoveTo(window_x1,window_y1);
  324.     LineTo(window_x2,window_y2);
  325. }
  326.  
  327. /************************************************************************
  328. *    Move present pen position to new position using view
  329. *    coordinates.  Nothing is drawn.
  330. ************************************************************************/
  331. void    move_to(double x,double y)
  332. {
  333.     int        window_x,
  334.             window_y;
  335.             
  336.     window_x = transform_x(x);
  337.     window_y = transform_y(y);
  338.     
  339.     MoveTo(window_x,window_y);
  340.     return;
  341. }
  342.  
  343. /************************************************************************
  344. *    Draw from present pen position to new position using view
  345. *    coordinates.
  346. ************************************************************************/
  347. void    draw_to(double x,double y)
  348. {
  349.     int        window_x,
  350.             window_y;
  351.             
  352.     window_x = transform_x(x);
  353.     window_y = transform_y(y);
  354.     
  355.     LineTo(window_x,window_y);
  356.     return;
  357. }
  358.  
  359. /************************************************************************
  360. *    draw_circle() draws a circle using view coordinates.
  361. ************************************************************************/
  362. void draw_circle(double center_x,double center_y,double r)
  363. {
  364.     Rect    myRect,
  365.             *myRectPtr;
  366.     int        window_x,
  367.             window_y,
  368.             window_r;
  369.             
  370.     window_x = transform_x(center_x);
  371.     window_y = transform_y(center_y);
  372.     window_r = (int) (r*(double) gGraphWidth/gViewWidth);
  373.     
  374.     myRectPtr = &myRect;
  375.     
  376.     myRectPtr->left = window_x-window_r;
  377.     myRectPtr->right = window_x+window_r;
  378.     myRectPtr->top = window_y-window_r;
  379.     myRectPtr->bottom = window_y+window_r;
  380.     
  381.     FrameOval(&myRect);
  382.     return;         
  383. }
  384.  
  385. /************************************************************************
  386. *    fill_circle() draws a circle using view coordinates.  The circle
  387. *    is filled with the present pen color
  388. ************************************************************************/
  389. void fill_circle(double center_x,double center_y,double r)
  390. {
  391.     Rect    myRect,
  392.             *myRectPtr;
  393.     int        window_x,
  394.             window_y,
  395.             window_r;
  396.             
  397.     window_x = transform_x(center_x);
  398.     window_y = transform_y(center_y);
  399.     window_r = (int) (r*(double) gGraphWidth/gViewWidth);
  400.     
  401.     myRectPtr = &myRect;
  402.     
  403.     myRectPtr->left = window_x-window_r;
  404.     myRectPtr->right = window_x+window_r;
  405.     myRectPtr->top = window_y-window_r;
  406.     myRectPtr->bottom = window_y+window_r;
  407.     
  408.     PaintOval(&myRect);
  409.     return;         
  410. }
  411.  
  412. /************************************************************************
  413. *    mouse_button_is_down() checks whether the mouse button is down,
  414. *    returns TRUE or FALSE.
  415. ************************************************************************/
  416. boolean        mouse_button_is_down(void)
  417. {
  418.     return Button();
  419. }
  420.  
  421. /************************************************************************
  422. *    get_mouse_location returns the mouse coordinates in terms of the 
  423. *    view coordinate system. It uses the inverse transformation of that
  424. *    in transform_x() and transform_y().
  425. ************************************************************************/
  426. void    get_mouse_location(double *x_ptr,double *y_ptr)
  427. {
  428.     Point        mouseLoc;
  429.     int            x,
  430.                 y;
  431.     
  432.     GetMouse(&mouseLoc);
  433.     x = mouseLoc.h;
  434.     y = mouseLoc.v;
  435.     *x_ptr = gViewX+(x-gGraphX)*gViewWidth/gGraphWidth;
  436.     *y_ptr = gViewY+(y-gGraphY)*gViewHeight/gGraphHeight;
  437.  
  438.     return;
  439. }
  440.     
  441. /************************************************************************
  442. *    wait until button is pressed
  443. ************************************************************************/
  444. void    wait(void)
  445. {
  446.     while (!mouse_button_is_down())
  447.         ;
  448. }
  449.